#ifndef __G_QUATERNION_H__
#define __G_QUATERNION_H__

#include "GUtilities/GTypes.h"

#include "GVector3.h"

namespace GMath
{

	class GQuaternion
	{
	public:
		static const GQuaternion Identitiy;

		union
		{
			struct
			{
				float		x;
				float		y;
				float		z;
				float		w;
			};

			float			Arr[4];
		};

							GQuaternion();
							GQuaternion(const GVector3& Axis, float Angle);
							GQuaternion(float RotX, float RotY, float RotZ);
							GQuaternion(float Qx, float Qy, float Qz, float Qw);
							GQuaternion(const GVector3& Tangent, const GVector3& Binormal, const GVector3& Normal);

							operator float* ();
							operator const float* ()const;

		void				Normalize();
		static void			Normalize(OUTPUT GQuaternion& Output, const GQuaternion& Quaternion);

		void				Conjugate();
		static void			Conjugate(OUTPUT GQuaternion& Output, const GQuaternion& Quaternion);

		static void			Multiply(OUTPUT GVector3& Output, const GVector3& Vector, const GQuaternion& Quaternion);
		static void			Multiply(OUTPUT GQuaternion& Output, const GQuaternion& QuaternionA, const GQuaternion& QuaternionB);

		static void			Convert(OUTPUT GVector3& OutAxis, OUTPUT float& OutAngle, const GQuaternion& Quaternion);
		static void			Convert(OUTPUT float& OutRotX, OUTPUT float& OutRotY, OUTPUT float& OutRotZ, const GQuaternion& Quaternion);

		GQuaternion&		operator += (const GQuaternion& Quaternion);
		GQuaternion&		operator -= (const GQuaternion& Quaternion);
		GQuaternion&		operator *= (const GQuaternion& Quaternion);
		GQuaternion&		operator *= (float Value);
		GQuaternion&		operator /= (float Value);

		GQuaternion			operator + () const;
		GQuaternion			operator - () const;

		GQuaternion			operator + (const GQuaternion& Quaternion) const;
		GQuaternion			operator - (const GQuaternion& Quaternion) const;
		GQuaternion			operator * (const GQuaternion& Quaternion) const;
		GQuaternion			operator * (float Value) const;
		GQuaternion			operator / (float Value) const;

		bool				operator == (const GQuaternion& Quaternion) const;
		bool				operator != (const GQuaternion& Quaternion) const;

		friend GQuaternion	operator * (float Value, const GQuaternion& Quaternion);
		friend GQuaternion	operator / (float Value, const GQuaternion& Quaternion);
	
	};

}

#endif